#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
WebDAV完整功能测试脚本
"""

import requests
import json
from datetime import datetime
import time

class WebDAVCompleteTester:
    def __init__(self, base_url, username, password):
        self.base_url = base_url.rstrip('/')
        self.username = username
        self.password = password
        self.session = requests.Session()
        self.session.auth = (username, password)
        self.test_results = []
        
    def log_test(self, test_name, success, message, details=None):
        """记录测试结果"""
        result = {
            'test_name': test_name,
            'success': success,
            'message': message,
            'timestamp': datetime.now().isoformat(),
            'details': details or {}
        }
        self.test_results.append(result)
        
        status = "✅" if success else "❌"
        print(f"{status} {test_name}: {message}")
        if details:
            for key, value in details.items():
                print(f"   {key}: {value}")
    
    def test_server_connection(self):
        """测试服务器连接"""
        try:
            response = self.session.get(f"{self.base_url}/")
            success = response.status_code == 200
            self.log_test("服务器连接测试", success, f"状态码: {response.status_code}")
            return success
        except Exception as e:
            self.log_test("服务器连接测试", False, f"连接失败: {e}")
            return False
    
    def test_webdav_options(self):
        """测试WebDAV OPTIONS"""
        try:
            response = self.session.options(f"{self.base_url}/dav")
            success = response.status_code == 200
            
            allowed_methods = response.headers.get('Allow', '')
            dav_header = response.headers.get('DAV', '')
            
            self.log_test("WebDAV OPTIONS测试", success, f"状态码: {response.status_code}", {
                'Allowed Methods': allowed_methods,
                'DAV': dav_header
            })
            return success
        except Exception as e:
            self.log_test("WebDAV OPTIONS测试", False, f"请求失败: {e}")
            return False
    
    def test_file_operations(self):
        """测试文件操作"""
        test_file = "test_file.txt"
        test_content = "测试文件内容"
        
        try:
            # 1. 创建文件
            response = self.session.put(f"{self.base_url}/dav/{test_file}", data=test_content)
            create_success = response.status_code in [200, 201, 204]
            
            # 2. 读取文件
            read_response = self.session.get(f"{self.base_url}/dav/{test_file}")
            read_success = read_response.status_code == 200 and read_response.text == test_content
            
            # 3. 删除文件
            delete_response = self.session.delete(f"{self.base_url}/dav/{test_file}")
            delete_success = delete_response.status_code in [200, 204]
            
            success = create_success and read_success and delete_success
            
            self.log_test("文件操作测试", success, f"创建: {create_success}, 读取: {read_success}, 删除: {delete_success}", {
                'create_status': response.status_code if create_success else 'failed',
                'read_status': read_response.status_code if read_success else 'failed',
                'delete_status': delete_response.status_code if delete_success else 'failed'
            })
            return success
            
        except Exception as e:
            self.log_test("文件操作测试", False, f"操作失败: {e}")
            return False
    
    def test_directory_operations(self):
        """测试目录操作"""
        test_dir = "test_dir"
        
        try:
            # 1. 创建目录
            response = self.session.request('MKCOL', f"{self.base_url}/dav/{test_dir}")
            create_success = response.status_code in [200, 201, 204]
            
            # 2. 删除目录
            response = self.session.delete(f"{self.base_url}/dav/{test_dir}")
            delete_success = response.status_code in [200, 204]
            
            success = create_success and delete_success
            
            self.log_test("目录操作测试", success, f"创建: {create_success}, 删除: {delete_success}", {
                'create_status': response.status_code if create_success else 'failed',
                'delete_status': response.status_code if delete_success else 'failed'
            })
            return success
            
        except Exception as e:
            self.log_test("目录操作测试", False, f"操作失败: {e}")
            return False
    
    def test_move_copy_operations(self):
        """测试移动和复制操作"""
        source_file = "source_file.txt"
        dest_file = "dest_file.txt"
        test_content = "移动复制测试内容"
        
        try:
            # 1. 创建源文件
            response = self.session.put(f"{self.base_url}/dav/{source_file}", data=test_content)
            create_success = response.status_code in [200, 201, 204]
            
            # 2. 移动文件
            response = self.session.request('MOVE', f"{self.base_url}/dav/{source_file}", 
                                          headers={'Destination': f"{self.base_url}/dav/{dest_file}"})
            move_success = response.status_code in [200, 201, 204]
            
            # 3. 复制文件
            response = self.session.request('COPY', f"{self.base_url}/dav/{dest_file}", 
                                          headers={'Destination': f"{self.base_url}/dav/{source_file}"})
            copy_success = response.status_code in [200, 201, 204]
            
            # 4. 清理文件
            self.session.delete(f"{self.base_url}/dav/{source_file}")
            self.session.delete(f"{self.base_url}/dav/{dest_file}")
            
            success = create_success and move_success and copy_success
            
            self.log_test("移动复制操作测试", success, f"创建: {create_success}, 移动: {move_success}, 复制: {copy_success}", {
                'create_status': response.status_code if create_success else 'failed',
                'move_status': response.status_code if move_success else 'failed',
                'copy_status': response.status_code if copy_success else 'failed'
            })
            return success
            
        except Exception as e:
            self.log_test("移动复制操作测试", False, f"操作失败: {e}")
            return False
    
    def test_propfind_operations(self):
        """测试PROPFIND操作"""
        try:
            # 1. 创建测试文件
            test_file = "propfind_test.txt"
            response = self.session.put(f"{self.base_url}/dav/{test_file}", data="PROPFIND测试内容")
            if response.status_code not in [200, 201, 204]:
                self.log_test("PROPFIND操作测试", False, "创建测试文件失败")
                return False
            
            # 2. PROPFIND请求
            response = self.session.request('PROPFIND', f"{self.base_url}/dav/{test_file}", 
                                          headers={'Depth': '0'})
            propfind_success = response.status_code == 207
            
            # 3. 清理文件
            self.session.delete(f"{self.base_url}/dav/{test_file}")
            
            self.log_test("PROPFIND操作测试", propfind_success, f"状态码: {response.status_code}")
            return propfind_success
            
        except Exception as e:
            self.log_test("PROPFIND操作测试", False, f"操作失败: {e}")
            return False
    
    def test_chinese_filename(self):
        """测试中文文件名"""
        test_file = "中文测试文件.txt"
        test_content = "中文文件名测试内容"
        
        try:
            # 1. 创建中文文件名文件
            response = self.session.put(f"{self.base_url}/dav/{test_file}", data=test_content)
            create_success = response.status_code in [200, 201, 204]
            
            # 2. 读取中文文件名文件
            read_response = self.session.get(f"{self.base_url}/dav/{test_file}")
            read_success = read_response.status_code == 200 and read_response.text == test_content
            
            # 3. 删除中文文件名文件
            delete_response = self.session.delete(f"{self.base_url}/dav/{test_file}")
            delete_success = delete_response.status_code in [200, 204]
            
            success = create_success and read_success and delete_success
            
            self.log_test("中文文件名测试", success, f"创建: {create_success}, 读取: {read_success}, 删除: {delete_success}", {
                'create_status': response.status_code if create_success else 'failed',
                'read_status': read_response.status_code if read_success else 'failed',
                'delete_status': delete_response.status_code if delete_success else 'failed'
            })
            return success
            
        except Exception as e:
            self.log_test("中文文件名测试", False, f"操作失败: {e}")
            return False
    
    def test_large_file(self):
        """测试大文件操作"""
        test_file = "large_file.txt"
        # 创建1MB的测试内容
        test_content = "A" * (1024 * 1024)  # 1MB
        
        try:
            # 1. 创建大文件
            response = self.session.put(f"{self.base_url}/dav/{test_file}", data=test_content)
            create_success = response.status_code in [200, 201, 204]
            
            # 2. 读取大文件
            read_response = self.session.get(f"{self.base_url}/dav/{test_file}")
            read_success = read_response.status_code == 200 and len(read_response.text) == len(test_content)
            
            # 3. 删除大文件
            delete_response = self.session.delete(f"{self.base_url}/dav/{test_file}")
            delete_success = delete_response.status_code in [200, 204]
            
            success = create_success and read_success and delete_success
            
            self.log_test("大文件操作测试", success, f"创建: {create_success}, 读取: {read_success}, 删除: {delete_success}", {
                'file_size': f"{len(test_content) / 1024 / 1024:.1f}MB",
                'create_status': response.status_code if create_success else 'failed',
                'read_status': read_response.status_code if read_success else 'failed',
                'delete_status': delete_response.status_code if delete_success else 'failed'
            })
            return success
            
        except Exception as e:
            self.log_test("大文件操作测试", False, f"操作失败: {e}")
            return False
    
    def run_all_tests(self):
        """运行所有测试"""
        print("🚀 开始WebDAV完整功能测试")
        print("=" * 80)
        print(f"测试目标: {self.base_url}/dav")
        print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("=" * 80)
        
        start_time = time.time()
        
        # 运行测试
        tests = [
            self.test_server_connection,
            self.test_webdav_options,
            self.test_file_operations,
            self.test_directory_operations,
            self.test_move_copy_operations,
            self.test_propfind_operations,
            self.test_chinese_filename,
            self.test_large_file
        ]
        
        passed = 0
        for test in tests:
            if test():
                passed += 1
        
        duration = time.time() - start_time
        
        # 输出结果
        print("\n" + "=" * 80)
        print("📊 测试结果汇总")
        print("=" * 80)
        print(f"总测试数: {len(tests)}")
        print(f"通过测试: {passed}")
        print(f"失败测试: {len(tests) - passed}")
        print(f"成功率: {passed/len(tests)*100:.1f}%")
        print(f"测试耗时: {duration:.2f}秒")
        
        # 显示失败的测试
        failed_tests = [result for result in self.test_results if not result['success']]
        if failed_tests:
            print("\n❌ 失败的测试:")
            for test in failed_tests:
                print(f"  - {test['test_name']}: {test['message']}")
        
        # 保存报告
        report = {
            'total': len(tests),
            'passed': passed,
            'failed': len(tests) - passed,
            'success_rate': passed/len(tests)*100,
            'duration': duration,
            'results': self.test_results
        }
        
        report_file = f"test/webdav_complete_test_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(report_file, 'w', encoding='utf-8') as f:
            json.dump(report, f, ensure_ascii=False, indent=2)
        
        print(f"\n📄 详细测试报告已保存到: {report_file}")
        
        return passed == len(tests)

if __name__ == "__main__":
    import argparse
    
    parser = argparse.ArgumentParser(description='WebDAV完整功能测试')
    parser.add_argument('--host', default='127.0.0.1', help='服务器地址')
    parser.add_argument('--port', default='8084', help='服务器端口')
    parser.add_argument('--username', default='testuser', help='用户名')
    parser.add_argument('--password', default='testpass123', help='密码')
    
    args = parser.parse_args()
    
    base_url = f"http://{args.host}:{args.port}"
    
    tester = WebDAVCompleteTester(base_url, args.username, args.password)
    success = tester.run_all_tests()
    
    exit(0 if success else 1)
